#pragma once
#ifndef __TSGCONTROLLER__
#define __TSGCONTROLLER__


#include "tsgCore.h"


namespace tsg
{
	/** Library provided animation controllers.  You should not add anything to this namespace. */
	namespace controller
	{


		/** The current application time.  Output is the number of seconds since the application began. Most animated %tsg graphs will use this as the root controller for providing the passage of time. @deprecated ApplicationTime2 has replaced this class. */
		class ApplicationTime : public Controller<float>
		{
		public:
			Parameter<float>  master;
		public:
			/** Default constructor. */
			ApplicationTime();
		private:
			void  doUpdate();
		};


		/** The current application time and previous frame elapsed time. Output is in seconds since the application began. Most animated %tsg graphs will use this as the root controller for providing the passage of time. */
		class ApplicationTime2 : public Controller2
		{
		public:
			Parameter<float>  frameTime; /**< [Output] Elapsed time since the last frame. */
			Parameter<float>  time;      /**< [Output] Current application time. */
		public:
			/** Default constructor. */
			ApplicationTime2();
			~ApplicationTime2();
		private:
			void  doUpdate();
		};


		/** Example controller.  This controller does not represent any sensible animation, but it does show an example of declaring and using a controller. */
		class Wibble : public Controller<float>
		{
		public:
			Parameter<float>  amplitudeA; /**< An example parameter. This can be animated by connecting it from a controllers output. */
			Parameter<float>  amplitudeB;
			Parameter<float>  amplitudeC;
			Parameter<float>  frequency;
			Parameter<float>  offset;
			Parameter<float>  time; /**< The time input parameter.  This will usually be hooked up to the ApplicationTime (or a controller itself linked to ApplicationTime). */
		public:
			Wibble ( );
		private:
			void  doUpdate ();
		};


		/** A base class to derive from when you wish to receive keyboard events. */
		class KeyboardObserver
		{
		public:
			KeyboardObserver( );
			~KeyboardObserver( );
		protected:
			/** Event method for when an ascii key is pressed. */
			virtual void  onKeyDown ( char key );
			/** Event method for when an ascii key is released. */
			virtual void  onKeyUp   ( char key );

			friend class KeyboardMaster;
		};


		/** A base class to derive from when you wish to receive mouse events. */
		class MouseObserver
		{
		public:
			MouseObserver( );
			~MouseObserver( );
		protected:
			/** Identified the three primary mouse buttons. */
			enum MouseButton { Left, Middle, Right };
		protected:
			/** Event method for when a mouse button is pressed. */
			virtual void  onButtonDown ( MouseButton button );
			/** Event method for when a mouse button is released. */
			virtual void  onButtonUp   ( MouseButton button );
			/** Event method for when the mouse is moved. */
			virtual void  onCursorMove ( int x, int y );

			friend class MouseMaster;
		};


		/** Mouse controllable view transform. */
		class InspectController : public Controller2, public MouseObserver
		{
		public:
			Parameter<float>         heading;
			Parameter<float>         inclination;
			Parameter<float>         distance;
			Parameter<Vector3>       interest;
			OutputParameter<Matrix>  xform;
		public:
			InspectController( bool y_up=false, float heading=0, float inclination=0, float distance=10 );
		protected:
			void  doUpdate( );
		protected:
			void  onButtonDown ( MouseButton button );
			void  onButtonUp   ( MouseButton button );
			void  onCursorMove ( int x, int y );
		private:
			int    _cursor[2];
			bool   _mode[2];
			bool   _y_up;
		};

	};
};


#endif
